#include "native/sun/misc/VM.h"

#include <stdexcept>
#include "rtda/heap/class.h"
#include "rtda/heap/string_pool.h"
#include "instructions/base/method_invoke_logic.h"

namespace jvm {
    namespace misc {

        const std::string VMNative::SUN_MISC_VM = "sun/misc/VM";

        //void VMNative::initialize(std::shared_ptr<rtda::Frame> frame) {
        //    auto&& classLoader = frame->getMethod()->getClass()->getLoder();
        //    auto&& jlSysClass = classLoader->loadClass("java/lang/System");
        //    auto&& initSysClass = jlSysClass->getStaticMethod("initializeSystemClass", "()V");
        //    instructions::invokeMethod(frame, initSysClass);
        //}

        void VMNative::initialize(std::shared_ptr<rtda::Frame> frame) {
            // hack: just make VM.savedProps nonempty
            auto vmClass = frame->getMethod()->getClass();
            if (!vmClass)
            {
                LOG_ERROR("null pointer!");
                throw std::runtime_error("null pointer!");
            }
            auto savedProps = vmClass->getRefVar("savedProps", "Ljava/util/Properties;");
            if (!savedProps)
            {
                LOG_ERROR("null pointer!");
                throw std::runtime_error("null pointer!");
            }
            auto loader = vmClass->getLoder();
            auto key = heap::StringPool::getInstance().JString(loader, "foo");
            auto val = heap::StringPool::getInstance().JString(loader, "bar");
            if (!key || !val)
            {
                LOG_ERROR("null pointer!");
                throw std::runtime_error("null pointer!");
            }
            auto&& stack = frame->getOperandStack();
            stack->pushRef(savedProps);
            stack->pushRef(key);
            stack->pushRef(val);
            auto propsClass = loader->loadClass("java/util/Properties");
            auto setPropMethod = propsClass->getInstanceMethod(
                "setProperty",
                "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;");
            instructions::invokeMethod(frame, setPropMethod);
        }

    } // namespace misc
} // namespace jvm